package com.xy.smartsms.facade;

import android.app.Activity;
import android.content.Context;

import com.xy.smartsms.data.ISmsPlugin;
import com.xy.smartsms.data.PublicInfoData;
import com.xy.smartsms.data.SmsItem;
import com.xy.smartsms.util.CommonUtils;
import com.xy.smartsms.util.JsonUtil;
import com.xy.smartsms.util.Log;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import cn.cmcc.online.smsapi.sdk.action.AbsSdkDoAction;


/**
 * 提供统一的卡片/菜单识别接口的外观类
 *
 * @author XIAOYUAN
 * @version 2.0
 */
public class SmsProcessFacade {
    private static final String TAG = SmsProcessFacade.class.getSimpleName();
    private static ExecutorService sCachePool = Executors.newFixedThreadPool(1);
    private static ExecutorService sPubicInfoPool = Executors.newFixedThreadPool(1);
    private Context mContext = null;
    private boolean mSafeCode = false;

    /**
     * 设置运营商识别超时时间，单位ms，不设置默认6000
     */
    public static final String KEY_PARSE_TIMEOUT = "custom_parse_time_out";
    /**
     * 设置使能安全码（不显示卡片）
     */
    public static final String KEY_SAFE_CODE = "enable_safe_code";
    /**
     * 设置默认使用的识别引擎
     */
    public static final String KEY_TOP_SWITCH = "top_switch_carrier";
    /**
     * 设置是否需要使用新的企业资料接口
     */
    public static final String KEY_PUBLIC_INFO = "new_public_info";
    /**
     * 设置是否需要使能远程识别
     */
    public static final String KEY_REMOTE_PARSE_ENABLE = "remote_parse_enable";
    /**
     * 设置提供远程服务的包名；默认为"com.xy.bizport"
     */
    public static final String KEY_REMOTE_PARSE_PACKAGE = "remote_parse_package";
    /**
     * 设置提供远程服务的ACTION名；默认为"com.xy.bizport.service.aidl.RemoteCallableStub"
     */
    public static final String KEY_REMOTE_PARSE_ACTION = "remote_parse_action";

    static private class CardResult {
        private int status;
        private int type;
        private JSONObject data;
        private long parseTime;
        private String sceneId;

        public JSONObject getData() {
            return data;
        }

        public CardResult setData(JSONObject data) {
            this.data = data;
            return this;
        }

        public long getParseTime() {
            return parseTime;
        }

        public int getStatus() {
            return status;
        }

        public CardResult setStatus(int status) {
            this.status = status;
            return this;
        }

        public int getType() {
            return type;
        }

        public CardResult setType(int type) {
            this.type = type;
            return this;
        }

        public CardResult setParseTime(long parseTime) {
            this.parseTime = parseTime;
            return this;
        }

        public String getSceneId() {
            return sceneId;
        }

        public CardResult setSceneId(String sceneId) {
            this.sceneId = sceneId;
            return this;
        }
    }

    static private class MenuResult {
        private int status;
        private long parseTime;
        private PublicInfoData data;

        public PublicInfoData getData() {
            return data;
        }

        public MenuResult setData(PublicInfoData data) {
            this.data = data;
            return this;
        }

        public long getParseTime() {
            return parseTime;
        }

        public MenuResult setParseTime(long parseTime) {
            this.parseTime = parseTime;
            return this;
        }

        public int getStatus() {
            return status;
        }

        public MenuResult setStatus(int status) {
            this.status = status;
            return this;
        }
    }

    /**
     * 卡片识别回调
     */
    public interface ISmsProcessCallback {
        /**
         * 卡片识别结果回调
         *
         * @param status   识别状态 @see ISmsPlugin.STATUS_SUCCESS ISmsPlugin.STATUS_FAIL
         * @param type     待识别卡片类型 @see ISmsPlugin.TYPE_RICH
         * @param cacheKey 当前识别结果的唯一识别ID
         * @param obj      识别结果
         * @note 识别状态即使为SUCCESS，识别结果也可能为空
         */
        void onCard(int status, int type, String cacheKey, JSONObject obj);
    }

    /**
     * 菜单/企业资料 识别回调
     */
    public interface ISmsProcessPublicInfoCallback {
        /**
         * 菜单识别结果回调
         *
         * @param phone 接入号码
         * @param data  识别结果
         */
        void onPublicInfo(String phone, PublicInfoData data);
    }

    private void getDefaultCard(final int type,
                                final SmsItem item,
                                final CardResult customResult,
                                final ISmsProcessCallback callback) {
        final long start = System.currentTimeMillis();
        Log.i(TAG, "getDefaultCard: " + " type=" + type + " id=" + item.getMsgId());
        SmsPluginManager.getInstance().getDefault().parseCard(type, item, new ISmsPlugin.ISmsPluginCallback() {
            @Override
            public void onCard(int status, int type, JSONObject obj) {
                if (status == ISmsPlugin.STATUS_FAIL) {
                    if (callback != null) {
                        callback.onCard(status, type, item.getCacheKey(), obj);
                    }

                    return;
                }

                if (callback != null) {
                    callback.onCard(status, type, item.getCacheKey(), obj);
                }
            }

            @Override
            public void onPublicInfo(int status, PublicInfoData data) {

            }
        });
    }

    /**
     * 异步获取卡片数据
     *
     * @param type     卡片类型 @see ISmsPlugin.TYPE_RICH ISmsPlugin.TYPE_SIMPLE ISmsPlugin.TYPE_FEATURE
     * @param item
     * @param callback
     * @remark item 的所有项都必须要正确设置
     */
    public void parseCard(final int type, final SmsItem item, final ISmsProcessCallback callback) {
        getDefaultCard(type, item, null, callback);
    }

    private void getDefaultMenu(final String phone,
                                final Map<String, String> extend,
                                final MenuResult customResult,
                                final ISmsProcessPublicInfoCallback callback) {
        final long start = System.currentTimeMillis();
        Log.i(TAG, "getDefaultMenu: " + " phone=" + phone);
        SmsPluginManager.getInstance().getDefault().parsePublicInfo(phone,
                extend,
                new ISmsPlugin.ISmsPluginCallback() {
                    @Override
                    public void onCard(int status, int type, JSONObject obj) {

                    }

                    @Override
                    public void onPublicInfo(int status, PublicInfoData data) {
                        if (callback != null) {
                            callback.onPublicInfo(phone, data);
                        }
                    }
                });
    }

    /**
     * 异步获取企业资料/菜单
     *
     * @param phone
     * @param callback
     * @deprecated
     */
    public void parsePublicInfo(final String phone,
                                final ISmsProcessPublicInfoCallback callback) {
        parsePublicInfo(phone, null, callback);
    }

    /**
     * 异步获取企业资料/菜单
     *
     * @param phone
     * @param callback
     */
    public void parsePublicInfo(final String phone,
                                final Map<String, String> extend,
                                final ISmsProcessPublicInfoCallback callback) {

        sPubicInfoPool.execute(new Runnable() {
            @Override
            public void run() {
                getDefaultMenu(phone, extend, null, callback);
            }
        });
    }

    /**
     * 处理菜单和按钮点击事件
     *
     * @param activity
     * @param action
     * @param extend
     */
    public void processAction(Activity activity, String action, Map<String, String> extend) {
        SmsPluginManager.getInstance().getDefault().processAction(activity, action, extend);
    }

    private SmsProcessFacade(Context context) {
        mContext = context;
        SmsPluginManager.getInstance(mContext);
    }

    /**
     * 初始化融合SDK
     *
     * @param sdkDoAction
     * @param extend      e.g.
     *                    HashMap<String, String> extend = new HashMap<String, String>();
     *                    extend.put(Constant.ONLINE_UPDATE_SDK, "1");
     *                    extend.put(Constant.SUPPORT_NETWORK_TYPE, "2");
     *                    extend.put(Constant.SMARTSMS_ENHANCE, Boolean.TRUE.toString());
     *                    extend.put(Constant.CHANNEL, BuildConfig.DUOQU_SDK_CHANNEL);
     *                    extend.put(Constant.SECRETKEY, BuildConfig.DUOQU_SDK_CHANNEL_SECRETKEY);
     *                    extend.put(Constant.RSAPRVKEY, BuildConfig.DUOQU_SDK_RSAKEY);
     * @remark sdkDoAction 需要被正确实现
     */
    public void init(final AbsSdkDoAction sdkDoAction, final Map<String, String> extend) {
        SmsPluginManager.getInstance().getDefault().init(sdkDoAction, extend);
        if (SmsPluginManager.getInstance().getCustom() != null) {
            SmsPluginManager.getInstance().getCustom().init(new ISmsPlugin.ISmsPluginAction() {
                @Override
                public List<SmsItem> getMessageList(String phone, long startTime, long endTime, int limit) {
                    List<JSONObject> jsonList = sdkDoAction.getReceiveMsgByReceiveTime(phone, startTime, endTime, limit);
                    if (jsonList == null) {
                        return null;
                    }

                    List<SmsItem> itemList = new ArrayList<SmsItem>();
                    for (JSONObject json : jsonList) {
                        String msgId = (String) JsonUtil.getValFromJsonObject(json, "msgId");
                        long receiveTime = Long.valueOf((String) JsonUtil.getValFromJsonObject(json, "smsReceiveTime"));
                        SmsItem item = new SmsItem().setMsgId(msgId)
                                .setBody((String) JsonUtil.getValFromJsonObject(json, "msg"))
                                .setPhone((String) JsonUtil.getValFromJsonObject(json, "phone"))
                                .setCacheKey(CommonUtils.getCacheKey(msgId, receiveTime))
                                .setReceiveTime(receiveTime);
                        itemList.add(item);
                    }

                    return itemList;
                }
            }, extend);
        }
    }

    private static SmsProcessFacade sSmsProcessFacade = null;

    /**
     * 简化版构造函数
     *
     * @return
     */
    public static SmsProcessFacade getInstance() {
        return sSmsProcessFacade;
    }

    /**
     * 构造函数
     *
     * @param context
     * @return
     */
    public static SmsProcessFacade getInstance(Context context) {
        synchronized (SmsProcessFacade.class) {
            if (sSmsProcessFacade == null) {
                sSmsProcessFacade = new SmsProcessFacade(context);
            }
        }

        return sSmsProcessFacade;
    }

    /**
     * 将号码的识别结果从数据库加载到缓存
     *
     * @param phone
     * @note prefetch在主线程中调用以保障预取在实际获取之前；加载本身需要在工作线程中完成
     */
    public void loadCache(final String phone) {
        Log.i(TAG, "loadCache: prefetch");
        sCachePool.execute(new Runnable() {
            @Override
            public void run() {
                SmsPluginManager.getInstance().getDefault().loadCache(phone);
                if (SmsPluginManager.getInstance().getCustom() != null) {
                    SmsPluginManager.getInstance().getCustom().loadCache(phone);
                }
            }
        });
    }

    /**
     * 后台识别，以提升性能
     *
     * @param phone null: 以短信接收时间倒序的所有信息; not null: 仅识别该号码下的短信
     * @param limit 一次识别的短信条数
     */
    public void backgroundParse(String phone, int limit) {
        Log.v(TAG, "backgroundParse: " + phone + " limit=" + limit);
        SmsPluginManager.getInstance().getDefault().backgroundParse(phone, limit);
        if (SmsPluginManager.getInstance().getCustom() != null) {
            SmsPluginManager.getInstance().getCustom().backgroundParse(phone, limit);
        }
    }

    /**
     * 清除缓存以释放RAM
     *
     * @param phone
     */
    public void clearCache(String phone) {
        Log.v(TAG, "clearCache: " + phone);
        SmsPluginManager.getInstance().getDefault().clearCache(phone);
        if (SmsPluginManager.getInstance().getCustom() != null) {
            SmsPluginManager.getInstance().getCustom().clearCache(phone);
        }
    }

    /**
     * 设置参数
     *
     * @param extend 同init的extend参数
     */
    public void setParam(Map<String, String> extend) {
        Log.i(TAG, "setParam: " + extend);
        SmsPluginManager.getInstance().getDefault().setParam(extend);
        if (SmsPluginManager.getInstance().getCustom() != null) {
            SmsPluginManager.getInstance().getCustom().setParam(extend);
        }
    }
}

